#include "header.h"

static double 	ph_time, tmax, tio, l, dx, dt, c1, Ntot;
static int 	i, myid, np, n, ind;
static time_str times;
static char	str[80], str2[80];
static FILE*    fh;

void init_timers(ctrl_ptr ctrl)
{
  tmax = ctrl->tmax;
  tio  = ctrl->tio;   c1 = 0.5 / ( 2 - pow(2, 1/3.) );
  l  = ctrl->l; n = ctrl->n;
  dx = l/n; times.ph_time = 0; times.io_time = 0;
  dt   =  (ctrl->cfl)*dx*dx; ind = 0;
}
double adv_time()
{
  MPI_Barrier(COMM);
  times.ph_time = times.ph_time + dt;
  MPI_Barrier(COMM);  
  return times.ph_time;
}

void measure_fft(work_ptr wrk, int num)
{
  MPI_Comm_size(COMM, &np);
  MPI_Comm_rank(COMM, &myid);
  MPI_Barrier(COMM);
  if (myid == 0) times.my_fft_time = clock();
  
  for (i = 0; i < num; i++) my_fft_bench(wrk);
  if (myid == 0) times.my_fft_time = (clock() - times.my_fft_time)/(double)CLOCKS_PER_SEC;
  MPI_Barrier(COMM);
  if (myid == 0) printf("%d FFTs. Avg speed %.4lf seconds\n", num, times.my_fft_time/num);
  MPI_Barrier(COMM);  
}
int stop_evolve()
{
  MPI_Barrier(COMM);
  if (times.ph_time >= tmax) return 0;
  else return 1;  
}

int time_out(work_ptr work, ctrl_ptr ctrl)
{
  MPI_Comm_rank(COMM, &myid);
  MPI_Barrier(COMM);  
  times.io_time = times.io_time + dt;
  if (times.io_time >= tio )
  {
    sprintf(str, "%s_%04d.bin",ctrl->runname, ind);
    sprintf(str2, "%s_%04d.dat",ctrl->runname, ind);
    if ((ctrl->m_order) == 4) {
      nnl_step(work, -c1*step(ctrl));
      lin_step(work, 0);
    }
    if ((ctrl->m_order) == 2) lin_step(work, -0.5*step(ctrl));
    Ntot = particles(work);
    if (myid == 0) printf("Wrote %s at time %f num particles %.15e\n",str, times.ph_time, Ntot);
    MPI_Barrier(COMM);  
    save_text(work, str2);
    //save_data(work, str );
    if ((ctrl->m_order) == 4) nnl_step(work, c1*step(ctrl));
    if ((ctrl->m_order) == 2) lin_step(work, 0.5*step(ctrl));
    MPI_Barrier(COMM);  
    ind++;
    times.io_time = 0.001*dt;
  }
  return 1;
}
void write_tempdata()
{
}

void save_temporal(work_ptr work, char* infile)
{
  fftw_complex 		tmp, tmp2;  
  double 		avgp, phase;
  MPI_Status 		status;
  int			n0;

  MPI_Comm_size(COMM, &np);
  MPI_Comm_rank(COMM, &myid);

  phase = 0;
  if (myid == np/2) {
    tmp = 0.125*(work->wrk[n/2+n*(n/2)] + work->wrk[n/2+n*(n/2-1)] + work->wrk[n/2-1+n*(n/2)] + work->wrk[n/2-1+n*(n/2-1)]);
    MPI_Recv(&tmp2, sizeof(fftw_complex), MPI_BYTE, np/2 - 1, 1, COMM, &status);
    tmp = tmp + tmp2;
    phase = atan2(cimag(tmp),creal(tmp));
  }
  if (myid == np/2 - 1){
    n0 = n/np;
    tmp=0.125*(work->wrk[n/2+n*(n/2+n0*(n0 - 1))]+work->wrk[n/2-1+n*(n/2+n0*(n0 - 1))]+work->wrk[n/2+n*(n/2-1+n0*(n0-1))]+work->wrk[n/2-1+n*(n/2-1+n0*(n0-1))]);
    MPI_Send(&tmp, sizeof(fftw_complex), MPI_BYTE, np/2, 1, COMM);
  }
  MPI_Barrier(COMM);
  //MPI_Allreduce(&phase,&avgp,1,MPI_DOUBLE, MPI_SUM, COMM);
  if (myid == np/2 ) {
     fh = fopen(infile,"a");
     fprintf(fh,"%f\t%e\n",(times.ph_time),phase);
     fclose(fh);
  }
  //printf("ID %d of %d Time %e\t Global phase %e\n", myid, np,  times.ph_time, phase);
}
